﻿using MetaVideoEditorEvolved.Engine;
namespace MetaVideoEditorEvolved.Helper
{
	using System.IO;
	using System.Linq.Expressions;
	using System.Text;
	using mveEngine;
	using System.Collections.Generic;
	using System.Windows.Forms;
	using MetaVideoEditorEvolved.Entity;
	using System.Linq;
	using System;
	using System.Diagnostics;
	using System.Net;
	using MetaVideoEditorEvolved.UI;
	

	public class KernelHelper : IKernelHelper
	{
		public List<MediaItem> RetrieveMainNodesAsMediaItems()
		{
			List<MediaItem> items = new List<MediaItem>();

			foreach (TreeNode node in mveEngine.Kernel.Instance.ItemCollection.MainNodes)
			{
				items.Add(CreateItem(node));
			}

			return items;
		}

		public string ValidateModifiedItemCollection()
		{
			return string.Empty;
		}

		public string ValidateItem(UI.Entity.VideoMediaElement itemToValidate)
		{
			StringBuilder message = new StringBuilder();

			if (itemToValidate.Backdrops.Any())
			{
				// Validate number of backdrops doesn't exceed config max
				var maxBackdrops = itemToValidate.Backdrops.Where(backdrop => backdrop.Checked);

				if (maxBackdrops.Count() > mveEngine.Config.Instance.MaxBdSaved)
				{
					message.Append(this.GetString("MaxBackdropsExceeded") + itemToValidate.Title);
				}
			}

			if (itemToValidate.Posters.Any())
			{
				// Validate number of poster doesn't exceed config max
				var maxPosters = itemToValidate.Posters.Where(images => images.Checked);

				if (maxPosters.Count() > 1)
				{
					message.Append(this.GetString("MaxPosterExceeded") + itemToValidate.Title);
				}
			}

			return message.ToString();
		}
		
		public string ValidateItem(MediaItem itemToValidate)
		{
			if (itemToValidate.MveItem == null)
			{
				return string.Empty;
			}

			StringBuilder message = new StringBuilder();

			if (itemToValidate.MveItem.BackdropImagePaths != null &&
			    itemToValidate.MveItem.BackdropImagePaths.Any())
			{
				// Validate number of backdrops doesn't exceed config max
				var maxBackdrops = itemToValidate.MveItem.BackdropImagePaths.Where(backdrop => backdrop.Checked);

				if (maxBackdrops.Count() > mveEngine.Config.Instance.MaxBdSaved)
				{
					message.Append(this.GetString("MaxBackdropsExceeded") + itemToValidate.MveItem.Title);
				}
			}

			if (itemToValidate.MveItem.ImagesPaths != null &&
			    itemToValidate.MveItem.ImagesPaths.Any())
			{
				// Validate number of poster doesn't exceed config max
				var maxPosters = itemToValidate.MveItem.ImagesPaths.Where(images => images.Checked);

				if (maxPosters.Count() > 1)
				{
					message.Append(this.GetString("MaxPosterExceeded") + itemToValidate.MveItem.Title);
				}
			}

			return message.ToString();
		}

		public void SetSelectedItem(MediaItem selectedItem)
		{
			if (selectedItem != null)
			{
				mveEngine.Kernel.Instance.ItemCollection.SelectedItem = selectedItem.MveItem;
				mveEngine.Kernel.Instance.ItemCollection.SelectedNode = selectedItem.ToTreeNode();
			}
		}

		public void ClearCache()
		{
			DirectoryInfo di = new DirectoryInfo(ApplicationPaths.AppCachePath);
			foreach (FileInfo fi in di.GetFiles())
			{
				try
				{
					File.Delete(fi.FullName);
				}
				catch
				{
				}
			}
		}

		public mveEngine.Item AutoSearchMediaItem(MediaItem itemToSearch)
		{
			mveEngine.Kernel.Instance.ItemCollection.AutoSearchItem(itemToSearch.MveItem);

			// Item is changed in kernel, need to reflect into entity collection
			var itemUpdated = mveEngine.Kernel.Instance.ItemCollection.ItemsList.Where(item => item.Id == itemToSearch.MediaId.ToString());

			return itemUpdated.First();
		}
		
		public mveEngine.Item AutoSearchMediaItem(UI.Entity.VideoMediaElement itemToSearch)
		{
			var mveItem = KernelSessionManager.SessionInstance.RealKernel.ItemCollection.ItemsList.First((i)=>i.Id == itemToSearch.Id.ToString());
			
			var season = itemToSearch as UI.Entity.SeasonMediaItem;
			
			if(season != null)
			{
				if(string.IsNullOrEmpty(season.ParentSerie.PrimaryProviderId))
				{
					return mveItem;
				}
				
				mveItem.PrimaryProviderSerieId = season.ParentSerie.PrimaryProviderId;
			}
			
			var episode = itemToSearch as UI.Entity.EpisodeMediaItem;
			
			if(episode != null)
			{
				if(string.IsNullOrEmpty(episode.ParentSeason.ParentSerie.PrimaryProviderId))
				{
					return mveItem;
				}
				
				mveItem.PrimaryProviderSerieId = episode.ParentSeason.ParentSerie.PrimaryProviderId;
			}
			
			bool found = mveEngine.Kernel.Instance.ItemCollection.AutoSearchItem(mveItem);

			// Item is changed in kernel, need to reflect into entity collection
			var itemUpdated = mveEngine.Kernel.Instance.ItemCollection.ItemsList.Where(item => item.Id == itemToSearch.Id.ToString()).First();
			itemUpdated.HasChanged = found;
			
			var serie = itemToSearch as UI.Entity.SerieMediaItem;
			
			if(serie != null && found)
			{
				serie.PrimaryProviderId = itemUpdated.PrimaryProviderSerieId;
			}
			
			// Plugin for series update all season and episode in one search
//			if(found)
//			{
//				var serie = itemToSearch as UI.Entity.SerieMediaItem;
//				if (serie!=null) {
//					foreach (var season in serie.Seasons) {
//						var s = mveEngine.Kernel.Instance.ItemCollection.ItemsList.Where(item => item.Id == season.Id.ToString()).First();
//						s.CopyToMediaUiEntity(season);
//
//						foreach (var episode in season.Episodes) {
//							var e = mveEngine.Kernel.Instance.ItemCollection.ItemsList.Where(item => item.Id == episode.Id.ToString()).First();
//							e.CopyToMediaUiEntity(episode);
//						}
//					}
//				}
//			}

			return itemUpdated;
		}
		
		
		private MediaItem CreateItem(TreeNode element)
		{
			MediaItem item = null;

			var guidStr = element.Tag as string;

			if (!string.IsNullOrEmpty(guidStr))
			{

				var mve = mveEngine.Kernel.Instance.ItemCollection.ItemsList.Where(mveItem => mveItem.Id == guidStr).FirstOrDefault();

				switch (mve.Type)
				{
					case mveEngine.Entity.Movie:
						item = new MovieMediaItem();
						break;
					case mveEngine.Entity.Series:
						item = new SerieMediaItem();
						break;
					case mveEngine.Entity.Season:
						item = new SeasonMediaItem();
						break;
					case mveEngine.Entity.Episode:
						item = new EpisodeMediaItem();
						break;
					case mveEngine.Entity.Folder:
						item = new FolderMediaItem();
						break;
					default:
						break;
				}

				item.MediaId = new System.Guid(guidStr);
				item.MveItem = mve;
			}
			else
			{
				item = new FolderMediaItem();
			}

			item.Name = element.Name;

			foreach (TreeNode node in element.Nodes)
			{
				item.Childs.Add(CreateItem(node));
			}

			return item;
		}

		public string GetString(string key)
		{
			return mveEngine.Kernel.Instance.GetString(key);
		}


		public void SaveItem(MediaItem item)
		{
			mveEngine.Kernel.Instance.ItemCollection.SaveItem(item.MveItem);
		}

		public void SaveItem(UI.Entity.VideoMediaElement item)
		{
			var mveItem = KernelSessionManager.SessionInstance.RealKernel.ItemCollection.ItemsList.First((i)=>i.Id == item.Id.ToString());
			mveEngine.Kernel.Instance.ItemCollection.SaveItem(mveItem);
		}

		public void ClearCheckedItems()
		{
			Kernel.Instance.ItemCollection.CheckedItems.Clear();
		}


		public void ReloadItemCollection()
		{
			Kernel.Instance.ItemCollection = new mveEngine.ItemCollection(Config.Instance.RootFolders);
		}


		public void RefreshData()
		{
			mveEngine.Kernel.Instance.ItemCollection.RefreshData();
		}


		public Item LoadItemFromCache(string id)
		{
			var item = (Item)Serializer.Deserialization(System.IO.Path.Combine(ApplicationPaths.AppCachePath, id));
			
//			if(item.PrimaryImage != null &&
//			   !string.IsNullOrEmpty(item.PrimaryImage.Image))
//			{
//				ImageUtil.DeleteLocalCacheImage(item.PrimaryImage.Image);
//			}
//
//			if(item.PrimaryBackdrop != null &&
//			   !string.IsNullOrEmpty(item.PrimaryBackdrop.Image))
//			{
//				ImageUtil.DeleteLocalCacheImage(item.PrimaryBackdrop.Image);
//			}
			
			return item;
		}


		public void UpdateLocalItemWithOptionsFromPlugin(Item localItem, Item fetchedItem)
		{
//			ProvidersUtil.UpdateItem(localItem, fetchedItem);
		}


		public void InitKernel()
		{
			mveEngine.Kernel.Init();
			
			var preloadProvider = AddInProviderManager.Current;
			var preloadSaver = AddInSaverManager.Current;
			var preloadReader = AddInReaderManager.Current;
			var preloadExtraTools = AddInExtraToolsManager.Current;
		}


		public int ItemCount()
		{
			return mveEngine.Kernel.Instance.ItemCollection.ItemsList.Count;
		}

		public void LoadLocalDataAndSaveToCache(mveEngine.Item item)
		{
			if (item != null)
			{
				ProvidersUtil.LocalFetch(item);
				
				if(item.PrimaryImage != null &&
				   !string.IsNullOrEmpty(item.PrimaryImage.Image))
				{
					ImageUtil.DeleteLocalCacheImage(item.PrimaryImage.Image);
				}
				
				if(item.PrimaryBackdrop != null &&
				   !string.IsNullOrEmpty(item.PrimaryBackdrop.Image))
				{
					ImageUtil.DeleteLocalCacheImage(item.PrimaryBackdrop.Image);
				}
				
				// Save only if no error
				if(!item.IsInError)
				{
					string path = Path.Combine(ApplicationPaths.AppCachePath, item.Id);
					
					Serializer.Serialization(path, item);
				}
			}
		}

		public void PlayTrailer(string trailer)
		{
			if (File.Exists(Config.Instance.VlcPath))
			{
				Process vlc = new Process();
				vlc.StartInfo.FileName = Config.Instance.VlcPath;
				vlc.StartInfo.Arguments = "\"" + trailer + "\"";

				vlc.Start();
			}
		}

		private string DownloadAndConverteTrailerFile(UI.Entity.TrailerMediaItem trailerFile, UI.Entity.VideoMediaElement item, bool convert, VideoType format)
		{
			Tracer.TracerInstance.TraceInformation("Start downloading trailer " + trailerFile.FilePath);

			try
			{
				if (!Directory.Exists(Config.Instance.TrailerPath))
				{
					Directory.CreateDirectory(Config.Instance.TrailerPath);
				}

				int index = 0;
				for (int i = 0; i < item.Trailers.Count; i++)
				{
					if (item.Trailers[i].FilePath == trailerFile.FilePath)
					{
						index = i;
						break;
					}
				}

				string fileName = Path.GetFileName(trailerFile.FilePath);
				string localFile = Path.Combine(Config.Instance.TrailerPath, fileName);

				DownloadManager.RetrieveTrailer(trailerFile.FilePath, localFile);

				if (convert)
				{
					string convertedFile = string.Empty;

					Process vlc = new Process();
					vlc.StartInfo.CreateNoWindow = false;
					vlc.StartInfo.UseShellExecute = true;
					vlc.StartInfo.WorkingDirectory = Config.Instance.VlcPath.Replace(Path.GetFileName(Config.Instance.VlcPath), string.Empty);
					vlc.StartInfo.FileName = Config.Instance.VlcPath;

					if (format == VideoType.Mpg)
					{
						convertedFile = localFile.Replace(Path.GetExtension(localFile), ".mpg");
						vlc.StartInfo.Arguments = "\"" + localFile + "\" --sout=" +
							"#transcode{vcodec=mp2v,vb=4096,acodec=mp2a,ab=192,scale=1,channels=2,deinterlace,audio-sync}:standard{access=file,dst=\"" + convertedFile + "\",mux=ps} vlc://quit";
					}

					if (format == VideoType.Ts)
					{
						convertedFile = localFile.Replace(Path.GetExtension(localFile), ".ts");
						vlc.StartInfo.Arguments = "\"" + localFile + "\" --sout=" +
							"#transcode{vcodec=h264,acodec=mp3}:standard{access=file,dst=\"" + convertedFile + "\",mux=ts} vlc://quit";
					}

					vlc.Start();

					localFile = convertedFile;

				}

				var mveItem = KernelSessionManager.SessionInstance.RealKernel.ItemCollection.ItemsList.First(i=>i.Id == item.Id.ToString());
				
				for (int i = 0; i < mveItem.TrailerFiles.Count; i++) {
					if (mveItem.TrailerFiles[i] == trailerFile.FilePath) {
						mveItem.TrailerFiles[i] = localFile;
						break;
					}
				}
				
				
				this.SyncItemToEngine(mveItem);
				
				return localFile;
			}
			catch (Exception ex)
			{
				Tracer.TracerInstance.TraceError("Error downloading " + trailerFile.FilePath, ex);
				throw;
			}
		}


		public void CopyDataFromCache(Item newItem, Item itemFromCache)
		{
			newItem.Actors = itemFromCache.Actors;
			newItem.AspectRatio = itemFromCache.AspectRatio;
			newItem.BackdropImagePaths = itemFromCache.BackdropImagePaths;
			newItem.BannersPaths = itemFromCache.BannersPaths;
			newItem.Countries = itemFromCache.Countries;
			newItem.Crew = itemFromCache.Crew;
			newItem.DateAdded = itemFromCache.DateAdded;
			newItem.EpisodeNumber = itemFromCache.EpisodeNumber;
			newItem.Genres = itemFromCache.Genres;
			newItem.HasChanged = itemFromCache.HasChanged;
			newItem.ImagesPaths = itemFromCache.ImagesPaths;
			newItem.Mediatype = itemFromCache.Mediatype;
			newItem.MetadataLocation = itemFromCache.MetadataLocation;
			newItem.MPAARating = itemFromCache.MPAARating;
			newItem.OriginalTitle = itemFromCache.OriginalTitle;
			newItem.Overview = itemFromCache.Overview;
			newItem.Path = itemFromCache.Path;
			newItem.PrimaryBackdrop = itemFromCache.PrimaryBackdrop;
			newItem.PrimaryBanner = itemFromCache.PrimaryBanner;
			newItem.PrimaryImage = itemFromCache.PrimaryImage;
			newItem.ProvidersId = itemFromCache.ProvidersId;
			newItem.Rating = itemFromCache.Rating;
			newItem.RunningTime = itemFromCache.RunningTime;
			newItem.SeasonNumber = itemFromCache.SeasonNumber;
			newItem.SeriesName = itemFromCache.SeriesName;
			newItem.SortTitle = itemFromCache.SortTitle;
			newItem.Studios = itemFromCache.Studios;
			newItem.Title = itemFromCache.Title;
			newItem.TagLines = itemFromCache.TagLines;
			newItem.TrailerFiles = itemFromCache.TrailerFiles;
			newItem.Type = itemFromCache.Type;
			newItem.VideoFiles = itemFromCache.VideoFiles;
			newItem.Watched = itemFromCache.Watched;
			newItem.Year = itemFromCache.Year;
			newItem.PrimaryProviderSerieId = itemFromCache.PrimaryProviderSerieId;
		}


		public System.Collections.ObjectModel.Collection<string> ExtractAvailableMediaTypes()
		{
			var query = from media in KernelSessionManager.SessionInstance.KernelUiEntity.FlatListOfMediaItems
				where media is UI.Entity.VideoMediaElement
				select ((UI.Entity.VideoMediaElement) media).MediaType;
			
			return new System.Collections.ObjectModel.Collection<string>(query.Distinct().ToList());
		}


		public void ClearMetadata(UI.Entity.VideoMediaElement mediaItem)
		{
			//TODO: Need to delete image file, trailers via delete/cleanup plugin + sync to mve engine
			var mveItem = KernelSessionManager.SessionInstance.RealKernel.ItemCollection.FindById(mediaItem.Id.ToString());
			
			if (mveItem.Actors != null) {
				mveItem.Actors.Clear();
			}
			
			mveItem.AspectRatio = string.Empty;
			
			if (mveItem.BackdropImagePaths!=null) {
				mveItem.BackdropImagePaths.Clear();
			}
			
			if (mveItem.BannersPaths != null) {
				mveItem.BannersPaths.Clear();
			}
			
			if (mveItem.Countries!=null) {
				mveItem.Countries.Clear();
			}
			
			if (mveItem.Crew!=null) {
				mveItem.Crew.Clear();
			}
			
			mveItem.DateAdded = DateTime.MinValue;
			mveItem.EpisodeNumber = string.Empty;
			
			if (mveItem.Genres!=null) {
				mveItem.Genres.Clear();
			}
			
			mveItem.HasChanged = true;
			
			if (mveItem.ImagesPaths!=null) {
				mveItem.ImagesPaths.Clear();
			}
			
			mveItem.Mediatype = string.Empty;
			mveItem.MPAARating = string.Empty;
			mveItem.Overview = string.Empty;
			mveItem.PrimaryBackdrop = null;
			mveItem.PrimaryBanner = null;
			mveItem.PrimaryImage = null;
			
			if (mveItem.ProvidersId!=null) {
				mveItem.ProvidersId.Clear();
			}
			
			mveItem.Rating = null;
			mveItem.RunningTime = null;
			mveItem.SeasonNumber = string.Empty;
			mveItem.SortTitle = string.Empty;
			
			if (mveItem.Studios!=null) {
				mveItem.Studios.Clear();
			}
			
			if (mveItem.TagLines!=null) {
				mveItem.TagLines.Clear();
			}
			
			if (mveItem.TrailerFiles!=null) {
				mveItem.TrailerFiles.Clear();
			}
			
			mveItem.Watched = null;
			mveItem.Year = null;
			
			mveItem.CopyToMediaUiEntity(mediaItem);
		}
		
		public void SyncItemToEngine(Item newItem)
		{
			var itemInKernel = UI.KernelSessionManager.SessionInstance.RealKernel.ItemCollection.ItemsList.First(i=>i.Id == newItem.Id.ToString());
			this.CopyDataFromCache(itemInKernel, newItem);
		}
		
		public string DownloadTrailer(MetaVideoEditorEvolved.UI.Entity.TrailerMediaItem trailerFile, MetaVideoEditorEvolved.UI.Entity.VideoMediaElement item)
		{
			return this.DownloadAndConverteTrailerFile(trailerFile, item, false, VideoType.None);
		}
		
		public string DownloadAndConvertTrailer(MetaVideoEditorEvolved.UI.Entity.TrailerMediaItem trailerFile, MetaVideoEditorEvolved.UI.Entity.VideoMediaElement item, VideoType format)
		{
			return this.DownloadAndConverteTrailerFile(trailerFile, item, true, format);
		}
	}
}
